package com.greenline.push.service.core.send.base;

import javax.annotation.Resource;

import org.apache.log4j.Logger;

import com.alibaba.fastjson.JSON;
import com.greenline.push.core.enums.AppPacketSource;
import com.greenline.push.core.enums.MsgHisStatus;
import com.greenline.push.core.enums.MsgSendType;
import com.greenline.push.core.pushcenter.MsgForSendManager;
import com.greenline.push.core.pushcenter.MsgHisManager;
import com.greenline.push.core.pushcenter.MsgRetryFullManager;
import com.greenline.push.core.pushcenter.MsgRetryManager;
import com.greenline.push.dal.pushcenter.dataobject.MsgHisDO;
import com.greenline.push.dal.pushcenter.dataobject.MsgRetryDO;
import com.greenline.push.service.core.item.AppPacket;
import com.greenline.push.service.core.tmpl.AppChannelCache;
import com.greenline.push.service.core.utils.Constants;

/**
 * 
 * @Type AppPacketHandler
 * @Desc apppacket 的后续处理[入库,更新发送次数,删除已发消息 ...]
 * @author shuai.zuo
 * @date 2014年12月11日
 * @Version V1.0
 */
public class AppPacketHandler {
    @Resource
    private MsgRetryManager msgRetryManager;
    @Resource
    private MsgRetryFullManager msgRetryFullManager;
    @Resource
    private MsgForSendManager msgForSendManager;
    @Resource
    private MsgHisManager msgHisManager;
    @Resource
    private AppChannelCache appChannelCache;

    Logger log = Constants.LOG_PROCESS;

    /**
     * 
     * @param appPacket
     * @param flag
     * @param 默认发送失败 ,次数累加
     */
    public void afterSendOperation(AppPacket appPacket, boolean flag) {
        this.afterSendOperation(appPacket, flag, false);
    }

    /**
     * 
     * @param appPacket
     * @param flag
     * @param deleteDirect 如果发送失败, 是否直接删除 app packet ? [msg_retry]
     */
    public void afterSendOperation(AppPacket appPacket, boolean flag, boolean deleteDirect) {
        // msg_for_send must delete anyway unless msgtype==all because has been
        // deleted by task
        if (appPacket.getType() == MsgSendType.POINT.getType() || appPacket.getType() == MsgSendType.GROUP.getType())
            msgForSendManager.delete(appPacket.getDbMsgId());
        // handle msg_retry
        updateOrDeleteMsgRetry(appPacket, flag, deleteDirect);
    }

    /**
     * 发送失败,更新msg_try,如果次数超出，则删除重发表信息 or发送成功 ,删除
     * 
     * @desc here main handle msg_retry
     * @param deleteDirect 是否需要不再累加失败次数,直接删除?
     * @param appPacket
     * @return
     */
    private boolean updateOrDeleteMsgRetry(AppPacket appPacket, boolean flag, boolean deleteDirect) {
        if (appPacket.getSource() != AppPacketSource.FULL) {
            // true ==send succ #### false==send fail
            if (flag) {
                // insert msghis
                insertMsgHis(appPacket, null, MsgHisStatus.suc.getStatus());
                // delete msgretry
                msgRetryManager.delete(appPacket.getDbRetryId());
                return true;
            } else {
                if (deleteDirect) {
                    msgRetryManager.delete(appPacket.getDbRetryId());
                    insertMsgHis(appPacket, Constants.PACKET_DATA_ERROR, MsgHisStatus.fail.getStatus());
                    log.debug(String.format("apppacket%s失败.原因[%s]", JSON.toJSONString(appPacket), Constants.PACKET_DATA_ERROR));
                    return true;
                }
                MsgRetryDO object = msgRetryManager.getById(appPacket.getDbRetryId());
                int current = object.getFailCount() + 1;
                if (ISender.MAX_SEND_NUM <= current) {
                    // 不再发送,删掉
                    msgRetryManager.delete(appPacket.getDbRetryId());
                    // insert his log
                    insertMsgHis(appPacket, Constants.RETRY_OVERLOAD, MsgHisStatus.fail.getStatus());

                    log.debug(String.format("apppacket[context:%s,recvId:%s]失败.原因[%s]", appPacket.getContext(), appPacket.getRecvUserId(),
                            Constants.RETRY_OVERLOAD));

                    return true;
                } else {
                    // fail count +1
                    MsgRetryDO msgRetryDO = new MsgRetryDO();
                    msgRetryDO.setFailCount(object.getFailCount() + 1);
                    msgRetryDO.setId(object.getId());
                    log.debug(String.format("apppacket[%s]失败.失败次数增1.[%s]", appPacket.getContext(), Constants.INTERFACE_FAIL));
                    return msgRetryManager.update(msgRetryDO);
                }
            }
        } else {
            // msg_retry_full
            // true ==send & false==send fail
            if (flag) {
                // insert msghis
                insertMsgHis(appPacket, null, MsgHisStatus.suc.getStatus());
                // delete msgretry
                msgRetryFullManager.delete(appPacket.getDbRetryId());
                return true;
            } else {
                if (deleteDirect) {
                    msgRetryFullManager.delete(appPacket.getDbRetryId());
                    insertMsgHis(appPacket, Constants.PACKET_DATA_ERROR, MsgHisStatus.fail.getStatus());
                    log.debug(String.format("apppacket%s失败.数据删除。失败原因[%s]", JSON.toJSONString(appPacket), Constants.PACKET_DATA_ERROR));
                    return true;
                }
                MsgRetryDO object = msgRetryFullManager.getById(appPacket.getDbRetryId());
                int current = object.getFailCount() + 1;
                if (ISender.MAX_SEND_NUM <= current) {
                    // delete
                    msgRetryFullManager.delete(appPacket.getDbRetryId());
                    // insert his log
                    insertMsgHis(appPacket, Constants.RETRY_OVERLOAD, MsgHisStatus.fail.getStatus());
                    log.debug(String.format("apppacket%s失败.数据删除。失败原因[%s]", JSON.toJSON(appPacket), Constants.RETRY_OVERLOAD));
                    return true;
                } else {
                    // fail count +1
                    MsgRetryDO msgRetryDO = new MsgRetryDO();
                    msgRetryDO.setFailCount(object.getFailCount() + 1);
                    msgRetryDO.setId(object.getId());
                    log.info(String.format("apppacket%s失败.[%s]", JSON.toJSON(appPacket), Constants.INTERFACE_FAIL));
                    return msgRetryFullManager.update(msgRetryDO);
                }
            }
        }
    }

    private boolean insertMsgHis(AppPacket appPacket, String memo, int status) {
        MsgHisDO msgHisDO = new MsgHisDO();
        msgHisDO.setContent(JSON.toJSONString(appPacket));
        msgHisDO.setMemo(memo);
        msgHisDO.setReceiveId(appPacket.getRecvUserId());
        msgHisDO.setTemplateId(appPacket.getTemplateId());
        msgHisDO.setType(appPacket.getType());
        msgHisDO.setStatus(status);
        msgHisDO.setAppId(appPacket.getAppId());
        String channelType = appChannelCache.getChannel(appPacket.getAppChannelId()).getType();
        msgHisDO.setAppChannel(Integer.parseInt(channelType));
        msgHisDO.setMessageId(appPacket.getMessageId());// set message id,from
                                                        // class_message table
        msgHisDO.setUidList(appPacket.getUserids());
        return msgHisManager.insert(msgHisDO) > 0;
    }
}
